package com.mcp.client.transport;

import com.mcp.server.model.McpResponse;
import com.mcp.util.JsonUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

/**
 * HTTP+SSE传输实现
 * 通过HTTP POST发送请求，通过SSE接收服务器推送
 */
public class HttpSseTransport implements McpTransport {
    private static final String API_URL = "http://localhost:8081/api/mcp";
    private static final String SSE_URL = "http://localhost:8081/events";
    
    private final AtomicBoolean connected = new AtomicBoolean(false);
    private final ConcurrentMap<String, Consumer<McpResponse>> responseHandlers = new ConcurrentHashMap<>();
    
    public HttpSseTransport() {
        // 启动SSE连接
        startSseConnection();
    }
    
    private void startSseConnection() {
        new Thread(() -> {
            try {
                URL url = new URL(SSE_URL);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setRequestProperty("Accept", "text/event-stream");
                connection.setRequestProperty("Cache-Control", "no-cache");
                connection.setRequestProperty("Connection", "keep-alive");
                
                int responseCode = connection.getResponseCode();
                if (responseCode == 200) {
                    connected.set(true);
                    System.out.println("SSE连接已建立");
                    
                    BufferedReader reader = new BufferedReader(
                            new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
                    
                    String line;
                    StringBuilder eventData = new StringBuilder();
                    String eventType = null;
                    
                    while ((line = reader.readLine()) != null) {
                        line = line.trim();
                        
                        if (line.startsWith("event:")) {
                            eventType = line.substring(6).trim();
                        } else if (line.startsWith("data:")) {
                            String data = line.substring(5).trim();
                            eventData.append(data);
                        } else if (line.isEmpty() && eventType != null && eventData.length() > 0) {
                            // 处理完整事件
                            handleEvent(eventType, eventData.toString());
                            
                            // 重置事件数据
                            eventData.setLength(0);
                            eventType = null;
                        }
                    }
                } else {
                    System.err.println("SSE连接失败，响应码: " + responseCode);
                }
            } catch (Exception e) {
                System.err.println("SSE连接异常: " + e.getMessage());
            } finally {
                connected.set(false);
                System.out.println("SSE连接已关闭");
                
                // 尝试重新连接
                try {
                    Thread.sleep(5000); // 等待5秒后重试
                    startSseConnection();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }
    
    private void handleEvent(String eventType, String data) {
        try {
            if ("response".equals(eventType)) {
                McpResponse response = JsonUtils.fromJson(data, McpResponse.class);
                if (response != null && response.getId() != null) {
                    String id = response.getId().toString();
                    Consumer<McpResponse> handler = responseHandlers.get(id);
                    if (handler != null) {
                        handler.accept(response);
                        responseHandlers.remove(id);
                    }
                }
            } else if ("connected".equals(eventType)) {
                System.out.println("SSE连接确认: " + data);
            } else if ("heartbeat".equals(eventType)) {
                // 忽略心跳事件
            } else {
                System.out.println("收到未知事件: " + eventType + ", 数据: " + data);
            }
        } catch (Exception e) {
            System.err.println("处理SSE事件失败: " + e.getMessage());
        }
    }
    
    @Override
    public String send(String request) throws Exception {
        // 确保SSE连接已建立
        if (!connected.get()) {
            throw new IllegalStateException("SSE连接未建立");
        }
        
        URL url = new URL(API_URL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
        connection.setRequestProperty("Accept", "application/json");
        connection.setDoOutput(true);
        
        // 发送请求
        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = request.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }
        
        int responseCode = connection.getResponseCode();
        if (responseCode == 200) {
            try (BufferedReader br = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
                StringBuilder response = new StringBuilder();
                String responseLine;
                while ((responseLine = br.readLine()) != null) {
                    response.append(responseLine.trim());
                }
                return response.toString();
            }
        } else {
            throw new IOException("HTTP请求失败，响应码: " + responseCode);
        }
    }
    
    @Override
    public void close() throws Exception {
        // 这里无法真正关闭SSE连接，因为它是单向的
        // 可以设置一个标志，让线程在下次循环时退出
        connected.set(false);
    }
    
    /**
     * 注册响应处理器
     */
    public void registerResponseHandler(String requestId, Consumer<McpResponse> handler) {
        responseHandlers.put(requestId, handler);
    }
}